<?php

namespace pmvc\log;

use pmvc\util\StringUtil;

class Log {

	const TRACE	= 10;
	const DEBUG	= 20;
	const INFO	= 30;
	const WARN	= 40;
	const ERROR	= 50;
	const FATAL	= 60;

	private static $logCallback		= NULL;
	private static $formatCallback	= NULL;
	private static $logFile			= NULL;
	private static $currentLevel	= Log::WARN;

	public static function registerErrorHandlers() {
		set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
			Log::error("Error ".$errno." in ".$errfile." line ".$errline.": ".$errstr);
			return FALSE;
		});
		set_exception_handler(function($ex) {
			Log::error("Error ".$ex->getCode()." in ".$ex->getFile()." line ".$ex->getLine().": ".$ex->getMessage());
			return FALSE;
		});
	}
	
	public static function setLogCallback($logCallback) {
		Log::$logCallback = $logCallback;
	}
	
	public static function setFormatCallback($formatCallback) {
		Log::$formatCallback = $formatCallback;
	}
	
	public static function setLogFile($logFile) {
		Log::$logFile = $logFile;
	}

	public static function getLogFile() {
		return Log::$logFile;
	}

	public static function setLogLevel($level) {
		Log::$currentLevel = $level;
	}

	public static function getLogLevel() {
		return Log::$currentLevel;
	}

	private static function doLog($level, $args) {

		// bail early if possible
		if ($level<Log::$currentLevel) {
			return;
		}

		// set basic log callback
		if (Log::$logCallback==NULL) {
			Log::setLogCallback(function($message) {
				if (Log::getLogFile()==NULL) {
					// TODO: warn?
					return;
				}
			    $f = fopen(Log::getLogFile(), "a+");
			    fwrite($f, $message);
			    fclose($f);
			});
		}

		// set basic format function
		if (Log::$formatCallback==NULL) {
			$levelNames = Array(
				Log::TRACE 	=> "TRACE",
				Log::DEBUG 	=> "DEBUG",
				Log::INFO 	=> "INFO",
				Log::WARN 	=> "WARN",
				Log::ERROR 	=> "ERROR",
				Log::FATAL	=> "FATAL"
			);
			Log::setFormatCallback(function($level, $args)use($levelNames) {
				$message = array_shift($args);
				return "[".date('h:m:s m/d/y')." : ".$levelNames[$level]."] "
					.StringUtil::pstringArray($message, $args)."\n";
			});
		}
			
	    // format and log
	    $f = Log::$formatCallback;
	    $l = Log::$logCallback;
	    $l($f($level, $args));

	}

	public static function trace() {
		Log::doLog(Log::TRACE, func_get_args());
	}

	public static function debug() {
		Log::doLog(Log::DEBUG, func_get_args());
	}

	public static function info() {
		Log::doLog(Log::INFO, func_get_args());
	}

	public static function warn() {
		Log::doLog(Log::WARN, func_get_args());
	}

	public static function error() {
		Log::doLog(Log::ERROR, func_get_args());
	}

	public static function fatal() {
		Log::doLog(Log::FATAL, func_get_args());
	}

}

?>